iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 25
2
IoT

IoT沒那麼難!新手用JavaScript入門做自己的玩具~系列 第 26

[Day 25]-用JS控制Arduino吧!讓你實體轉動網頁上的東西!最狂的加速度應用(?!) - Johnny Five 之 Accelerometer 三軸加速度計 - 狂應用篇

  • 分享至 

  • xImage
  •  

IoT沒那麼難!新手用 JavaScript 入門做自己的玩具!(iT邦幫忙鐵人賽系列書)

★本系列文章已集結成冊,和系列文不同的是:

  • 本書使用大量的圖解來說明LED系列、多種感測器等原理。
  • 補足系列文程式碼的解說,增加逐行程式碼的詳細解說!
  • 全彩的書籍,用圖解的方式,讓讀者來理解Johnny-Five各種API的功能與效果,讓你不會只讀文字看到想睡覺而學不起來。

歡迎大家做出自己想要的玩具,為了樂趣而學習,讓學習變成你的樂趣!ヽ(・×・´)ゞ
讓Arduino也能用JavaScript創造出屬於自己的作品!

★購書連結-天瓏網路書局:
https://www.tenlong.com.tw/products/9789864345328

《IoT沒那麼難!新手用 JavaScript 入門做自己的玩具!(iT邦幫忙鐵人賽系列書)》
博客來、金石堂、momo、誠品、PChome、讀冊,均有販售喔!─=≡Σ((( つ•̀ω•́)つ
ISBN:9789864345328

連續兩天講解三軸加速度計,應該有比較了解一點吧.....

本魯宅:有的話請在留言處 +1 ~
謎之音:才沒有...ಠ_ಠ

今天要來把我 4 年前和 Amos 老師學的 CSS3 3D 技術運用在這次的應用上~ (ง๑ •̀_•́)ง

下音樂 again ~
登登楞登~登登~ (多拉A夢的音效)

「 瘋 狂 麥 塊 」~ (๑•̀ㅂ•́)و✧

故事是這樣開始的…

本魯宅以前遇到Amos老師學到了很多實用的技巧和應用)~ (心之音:謝謝老師)

回想4年前什麼都不會的我,還在新手村上課的時候~
記得老師出了一個作業是「 3D 選單」,Amos 老師那時候用CSS3寫出 3D 的 Box 超帥的!(✪ω✪)
所以我就沒有乖乖的寫作業,而是寫了.....

✿✿✿「 3D 8-bit 花 」 ✿✿✿  d(d'∀')
CodePen:https://codepen.io/tinatyc/full/mqqRpV

謎之音:這樣根本是沒交作業吧(ㆆᴗㆆ)...

而且這朵花是立體的超帥的!!能學到這個技術真是太好了~(。◕∀◕。)
現在就和我一起連接加速度器,讓我們實體轉動時,螢幕內的物件也可以一起轉動!!

怎麼做?想法是這樣的~

利用昨天 Accelerometer 物件返回值 pitchrollinclination 去改變 HTML 元素的 CSS3 屬性 "transform: rotateX(deg) rotateY(deg) rotateZ(deg); 角度!
隨著加速度器回傳的數值套用到CSS3上,實現轉動的感覺~

擷取 MDN - transform

'' transform CSS 屬性可以讓你修改 CSS 可視化格式模型(visual formatting model)的空間維度。使用此屬性,元素可以被平移、旋轉、縮放和傾斜。 ''

那麼開始吧!GOGO!ξ( ✿>◡❛)

透視 HTML

一個立方體的組成有上、下、左、右、前、後六個面所組成

所以需要六個 div

<div class="box">
  <div class="front">F</div>
  <div class="back">B</div>
  <div class="top">T</div>
  <div class="bottom">BT</div>
  <div class="left">L</div>
  <div class="right">R</div>
</div>

接著我們要使用魔法~(並不是
我們要使用 CSS 的 transform-style: preserve-3d;

transform-style 作用於子元素,所以我們要給它一個爸爸 div 父層,讓它繼承 preserve-3d 的屬性,讓原本只有 2 個軸度的 HTML 變成 3 軸,也就是 2D 變成 3D !

//宣告元素的子代應放置在3D空間中。
.box {
  transform-style: preserve-3d;
}

設定立方體的面

現在你會覺得很困惑~
為什麼告訴瀏覽器「我的HTML是3D元素喔!」,結果得到的是這個畫面!

正方形都疊在一起啦!!(ಠ益ಠ)

所以......
要繼續設定立方體各面的位置就定位!
因為現在 box 的孩子是立體的,但是 box 本身不是立體的,看起來當然就是平面囉~

box 沒爸爸,這時候就要給他一個爸爸 div (認親大會XD),外面再包一層 div ,讓 box 成為真正的 3D 立體物!ヽ(・×・´)ゞ

box 變 3D 後才看的到 box 的孩子進而定位~

<div class="space3d">  //阿公讓爸爸變3D
  <div class="box">  //爸爸讓孩子變3D
    // 以下都是孩子
    <div class="front">F</div>
    <div class="back">B</div>
    <div class="top">T</div>
    <div class="bottom">BT</div>
    <div class="left">L</div>
    <div class="right">R</div>
  </div>
</div>

接著你應該就會看到爸爸和孩子都變立體了~

如果想更了解定位和透視怎麼寫~

請找 Amos 老師教你~被打
不過我是說真的....
因為我 CSS 不是很強,但 CSS 很吃觀念!
老師在這一塊已經是大師等級 LV.99999 Master
真心推薦!Amos 老師喔(*´∀`)~♥

Amos 老師的 3D相關連結

CSSCOKE - CSS3 3D魔術方塊
CodePen - Pure CSS 3D - Pocket Rubik's Cube
Youtube CSScoke - CSS3 3D魔術方塊效果
Youtube CSScoke - CSS3 3D選單 作業優選

做好方塊之後~我們就可以來寫程式啦!
本魯宅:我 愛 程 式 !ε٩(๑> ₃ <)۶з

後端部分:

後端程式碼

var io = require('socket.io');
var express = require('express');
var five = require('johnny-five');

var board = new five.Board();
var app = express();

app.use(express.static('www'));
var server = app.listen(3000, function() {
  console.log('connected!');
});

var sio = io(server);

board.on('ready', function() {
  var accelerometer = new five.Accelerometer({
    controller: 'ADXL345',
  });

  sio.on('connection', function(socket) {
    accelerometer.on('change', data => {
      const { acceleration, inclination, orientation, pitch, roll, x, y, z } = accelerometer;
      // 送 返回值 給前端接收
      socket.emit('startData', {
        axis: data,
        pitch: pitch,
        roll: roll,
        acceleration: acceleration,
        inclination: inclination,
        orientation: orientation,
      });
    });
  });
});

前端部分

HTML

<div class="space3d">  //阿公讓爸爸變3D
  <div class="box">  //爸爸讓孩子變3D
    // 以下都是孩子
    <div class="front">F</div>
    <div class="back">B</div>
    <div class="top">T</div>
    <div class="bottom">BT</div>
    <div class="left">L</div>
    <div class="right">R</div>
  </div>
</div>

CSS Style

.space3d {
  width: 310px;
  height: 310px;
  border: 1px solid #5b4b00;
  margin: auto;
  position: relative;
  top: 25%;
  perspective: 0px;
  transform-style: preserve-3d;
  transition: 1s;
  /* transform: rotateX(45deg) rotateY(0deg) rotateZ(40deg); */
}

.box {
  width: 100px;
  height: 100px;
  /* border: 1px solid #0f0; */
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  margin: auto;
  transform-style: preserve-3d;
}

.box div {
  width: 100%;
  height: 100%;
  outline: 2px solid #000;
  position: absolute;
  top: 0;
  left: 0;
  font-size: 60px;
  text-align: center;
  line-height: 100px;
}

.box .front {
  transform: translateZ(50px);
  background-color: #ffc9b596;
}

.box .back {
  transform: rotateY(180deg) translateZ(50px);
  background-color: #ffc1078f;
}

.box .top {
  transform: rotateX(90deg) translateZ(50px);
  background-color: hsla(330, 100%, 60%, 0.5);
}

.box .bottom {
  transform: rotateX(270deg) translateZ(50px);
  background-color: #7fe0ff80;
}

.box .left {
  transform: rotateY(270deg) translateZ(50px);
  background-color: #d15eff80;
}

.box .right {
  transform: rotateY(90deg) translateZ(50px);
  background-color: #59e24596;
}

接下來是前端 JavaScript 的程式部分~

JavaScript

var socket = io.connect();

socket.on('startData', function(data) {
  // 當socket開始連線時,接收資料
  axis = data.axis; 
  x = axis.x.toFixed(3);
  y = axis.y.toFixed(3);
  z = axis.z.toFixed(3);
  pitch = (data.pitch * 10).toFixed(2);
  roll = (data.roll * 10).toFixed(2);
  acceleration = data.acceleration.toFixed(3);
  inclination = data.inclination.toFixed(2);
  orientation = data.orientation;

  //將接收到的數值印在 HTML 上
  $('.xAxis').text(x);
  $('.yAxis').text(y);
  $('.zAxis').text(z);
  $('.pitch').text(pitch);
  $('.roll').text(roll);
  $('.acceleration').text(acceleration);
  $('.inclination').text(inclination);
  $('.orientation').text(orientation);

  // 利用 transform 改變 box 的 XYZ 軸。
  $('.space3d').css('transform', 'rotateX(' + pitch + 'deg) rotateY(' + roll + 'deg) rotateZ(' + inclination + 'deg)' );
});

因為回傳數值小數點太多位,所以我用.toFixed(Num);小數點後 2~3位數以便閱讀;

一樣我們用 jQuery 的 .css() 函式一直呼叫改變 box 的 rotate 各個軸的角度(deg)。

  • rotateX 對應到 pitch
  • rotateY 對應到 roll
  • rotateZ 對應到 inclination

補充連結:

MDN - <transform-function>
https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function

這樣就完成啦! (*´∀´)~♥ 超帥的喔!!

因為今天Demo蠻好玩的,我有把完整影片傳到 Youtube 上

Johnny Five 之 Accelerometer 三軸加速度計 - 應用篇
https://youtu.be/pGHddpXAgOY

寫完鐵人賽後會陸續把本系列各個完整的 Demo 影片整理上傳上去~
那今天就到這邊啦~感謝大家收看!

文後

祝中華民國雙十節生日快樂~ (❛◡❛✿)

不知道CSS那邊有沒有解釋錯誤....
等待Amos師傅過來鞭我,師傅我準備好教鞭了! (シ_ _)シ


本系列的程式碼皆會上傳到 GitHub 上開源

2019ironman-JS-IoT :
https://github.com/tinatyc/2019ironman-JS-IoT

喜歡按個星星吧~乾蝦乾蝦<(_ _)>


團隊系列文:

CSScoke - 金魚都能懂的這個網頁畫面怎麼切 - 金魚都能懂了你還怕學不會嗎
Hina Hina - 陣列大亂鬥
阿斬 - Python 程式交易 30 天新手入門
Clarence - LINE bot 好好玩 30 天玩轉 LINE API
塔塔默 - 用Python開發的網頁不能放到Github上?Lektor說可以!!
Vita Ora - 好 Js 不學嗎 !? JavaScript 入門中的入門。


同步連載於blogger-King 學習前端之人生


上一篇
[Day 24]-用JS控制Arduino吧!不動看不懂!最狂的加速度解說! - Johnny Five 之 Accelerometer 三軸加速度計 - 實作篇
下一篇
[Day 26]-用JS控制Arduino吧!我達達的馬達聲~ - Johnny Five 之 Servo 伺服馬達 - 簡介篇
系列文
IoT沒那麼難!新手用JavaScript入門做自己的玩具~33
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
Vita Ora
iT邦新手 4 級 ‧ 2019-10-10 22:21:57

強者我朋友

在座的大家都是強者~/images/emoticon/emoticon12.gif

我要留言

立即登入留言